# -*- coding: utf-8 -*-
# @Author  : pony.guan
# @Time    : 2021/12/27 14:59
# Description: gui工具实现热冷库区库位互换

import time
import json
import sys
from datetime import datetime, timedelta, timezone
from threading import Thread

from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox
from PyQt5.QtCore import QObject, pyqtSignal, QSharedMemory
from untitled import Ui_MainWindow

from move_location import get_bins, send_message_to_kafka, log
from empty_container_move_out import get_empty_bin_codes, send_request


class SignalStore(QObject):
    """
    信号库
    """
    progress_update = pyqtSignal(int)
    progress_update1 = pyqtSignal(int)
    finish_task = pyqtSignal()
    finish_task1 = pyqtSignal()
    process_info = pyqtSignal(str)


so = SignalStore()


class MyMainForm(QMainWindow, Ui_MainWindow):
    """
    ui控件
    """

    def __init__(self, parent=None):
        super(MyMainForm, self).__init__(parent)
        self.setupUi(self)

        # 理库页
        self.pushButton.clicked.connect(self.handle_calc)

        # 信号和槽函数进行绑定
        so.progress_update.connect(self.set_progress)
        so.progress_update1.connect(self.set_progress1)

        so.finish_task.connect(self.finish_task_func)
        so.finish_task1.connect(self.finish_task_func1)
        so.process_info.connect(self.process_task_func)

        # 任务执行标记，不能同时做两个任务
        self.ongoing = False

        # 空箱出库页
        # self.pushButton_2.clicked.connect(self.handle_calc2)

        self.ongoing2 = False

    def handle_calc2(self) -> None:
        """
        pass
        :return:
        """
        if not self.radioButton.isChecked() and not self.radioButton_2.isChecked():
            return

        if self.ongoing2:
            QMessageBox.warning(self, 'Warning', 'Task in progress, please wait for completion')
            return

        # 进一步确认是否执行空位出库
        reply = QMessageBox.question(self, 'Question', 'About to start, continue or not?',
                                     QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel,
                                     QMessageBox.Cancel)
        if reply != QMessageBox.Yes:
            return

        quantity = self.spinBox_5.value()

        def worker_thread_func1(quantity, all_):
            print(quantity, all_)
            self.ongoing2 = True
            empty_bin_codes = get_empty_bin_codes(quantity, all_)
            so.progress_update1.emit(50)
            ret = send_request(empty_bin_codes)
            if ret:
                so.progress_update1.emit(100)
                so.finish_task1.emit()
                self.ongoing2 = False

        so.progress_update1.emit(15)
        if self.radioButton.isChecked():
            all_ = True
        else:
            all_ = False
        worker = Thread(target=worker_thread_func1, args=(quantity, all_))
        worker.start()

    def handle_calc(self) -> None:
        """
        pass
        :return:
        """

        def worker_thread_func(hot_cold_ratio: str, tasks_quantity: int, interval_time: int) -> None:
            """
            @desc 热区活跃程度最高的前tasks_quantity个箱子 与 冷区活跃程度最低的前tasks_quantity个箱子 库位互换
            :param hot_cold_ratio: 热冷库占比
            :param tasks_quantity: 理库任务数量
            :param interval_time: 时间区间(最近多少天)
            :return:
            """
            self.ongoing = True

            # 开始查询数据库
            so.progress_update.emit(5)
            bins, bins_ = get_bins(hot_cold_ratio, tasks_quantity, interval_time)
            so.process_info.emit('---query database ...----')
            so.process_info.emit('---Analytical data ...----')
            so.process_info.emit('---Parsing complete ...----')
            # 数据库查询完毕
            so.progress_update.emit(25)
            so.process_info.emit('---send message to kafka ...----')

            send_message_to_kafka(bins)

            log_msg = '\n'.join(['\t' + str(_) for _ in bins_])

            so.process_info.emit(json.dumps(bins_))

            log.warning('move_location_msg:' + '\n' + log_msg)

            so.progress_update.emit(50)
            for i in range(51, 101):
                time.sleep(0.1)
                so.progress_update.emit(i)

            so.process_info.emit('---Assignment task completed----')
            # 消息发送完毕
            # for i in range(1, 101):
            #     time.sleep(0.1)
            #     so.progress_update.emit(i)
            self.ongoing = False

            so.finish_task.emit()

        # 限定在北京时间19:00到24:00之间执行
        SHA_TZ = timezone(
            timedelta(hours=8),
            name='Asia/Shanghai',
        )
        utc_now = datetime.utcnow().replace(tzinfo=timezone.utc)
        beijing_now = utc_now.astimezone(SHA_TZ)
        if int(beijing_now.strftime('%H')) not in range(19, 24):
            QMessageBox.warning(self, 'Warning', 'The program can only be executed from 19:00 to 24:00 Beijing time')
            return

        if self.ongoing:
            QMessageBox.warning(self, 'Warning', 'Task in progress, please wait for completion')
            return

        # 进一步确认是否执行理库
        reply = QMessageBox.question(self, 'Question', 'About to start, continue or not?',
                                     QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel,
                                     QMessageBox.Cancel)
        if reply != QMessageBox.Yes:
            return

        # 热冷库比例
        hot_cold_ratio = self.comboBox_2.currentText()
        # 理库数量(库位交换数量)
        tasks_quantity = self.spinBox_3.value()
        # 时间区间(最近多少天)
        interval_time = self.spinBox_4.value()

        self.textBrowser.setText('')
        worker = Thread(target=worker_thread_func, args=(hot_cold_ratio, tasks_quantity, interval_time))
        worker.start()

    def set_progress(self, value: int) -> None:
        """
        :param value:
        :return:
        """
        self.progressBar.setValue(value)

    def set_progress1(self, value):
        self.progressBar_2.setValue(value)

    def finish_task_func(self) -> None:
        """
        pass
        """
        QMessageBox.information(self, 'Information', 'Assignment task completed！')

    def finish_task_func1(self):
        QMessageBox.information(self, 'Information', 'Send request completed！')

    def process_task_func(self, info: str):
        self.textBrowser.append(info)


def run():
    app = QApplication(sys.argv)

    # QSharedMemory 防止程序多开
    share = QSharedMemory()
    share.setKey("main_window")
    if share.attach():
        msg_box = QMessageBox()
        msg_box.setWindowTitle("tips")
        msg_box.setText("The program is already running!")
        msg_box.setIcon(QMessageBox.Information)
        msg_box.addButton("yes", QMessageBox.YesRole)
        msg_box.exec()
        sys.exit(-1)
    if share.create(1):
        myWin = MyMainForm()
        myWin.show()
        sys.exit(app.exec_())


if __name__ == "__main__":
    run()
